import {customRef} from 'vue';
//region MySet
class MySet<T> extends Set<T>{
	track!:() => void;
	private trigger!:() => void;
	constructor(iterable?:Iterable<T>){
		super();
		customRef((track,trigger) => {
			this.track=track;
			this.trigger=trigger;
			return {
				get:() => {
					return this;
				},
				set(){},
			};
		});
		if(iterable){
			this._addAll(iterable);
		}
	}
	private _add(value:T){
		super.add(value);
	}
	private _addAll(iterable:Iterable<T>){
		if(Array.isArray(iterable)){
			for(let i=0;i<iterable.length;++i){
				super.add(iterable[i]);
			}
		}else{
			for(const value of iterable){
				super.add(value);
			}
		}
	}
	private _deleteAll(iterable:Iterable<T>){
		if(Array.isArray(iterable)){
			for(let i=0;i<iterable.length;++i){
				super.delete(iterable[i]);
			}
		}else{
			for(const value of iterable){
				super.delete(value);
			}
		}
	}
	private _autoTrigger<R>(fn:() => R):R{
		const oldSize=this.size;
		const res=fn();
		if(oldSize!==this.size){
			this.trigger();
		}
		return res;
	}
	add(value:T):this{
		this._autoTrigger(() => {
			super.add(value);
		});
		return this;
	}
	addAll(iterable:Iterable<T>):this{
		this._autoTrigger(() => {
			this._addAll(iterable);
		});
		return this;
	}
	delete(value:T):boolean{
		return this._autoTrigger(() => {
			return super.delete(value);
		});
	}
	deleteAll(iterable:Iterable<T>):this{
		this._autoTrigger(() => {
			this._deleteAll(iterable);
		});
		return this;
	}
	clear():void{
		this._autoTrigger(() => {
			super.clear();
		});
	}
	some(predicate:(value:T,index:number) => boolean):boolean{
		let index=0;
		for(const item of this){
			if(predicate(item,index++)){
				return true;
			}
		}
		return false;
	}
	every(predicate:(value:T,index:number) => boolean):boolean{
		let index=0;
		for(const item of this){
			if(!predicate(item,index++)){
				return false;
			}
		}
		return true;
	}
	filter(predicate:(value:T,index:number) => boolean):MySet<T>{
		const set=new MySet<T>();
		let index=0;
		for(const item of this){
			if(predicate(item,index++)){
				set._add(item);
			}
		}
		return set;
	}
	get value(){
		this.track();
		return this;
	}
}
//endregion
//region 判断路由参数是否包含
function routeIncludesParams(
	outer:Record<string,string|string[]>,
	inner:Record<string,string|string[]>,
):boolean{
	for(const key in inner){
		const innerValue=inner[key];
		const outerValue=outer[key];
		if(innerValue===''){
			continue;
		}
		if(typeof innerValue==='string'){
			if(innerValue!==outerValue) return false;
		}else{
			if(
				!Array.isArray(outerValue)||
				outerValue.length!==innerValue.length||
				innerValue.some((value,i) => value!==outerValue[i])
			){
				return false;
			}
		}
	}
	return true;
}
//endregion
export {
	MySet,
	routeIncludesParams,
};